This hack is no longer needed as it is implemented in the official docker images, in this PR
Saleor as mentioned in its landing page is
An open-source, GraphQL-first e-commerce platform delivering ultra-fast, dynamic and personalized shopping experiences.
Saleor is built as separate components
saleor-core
which is the graphql apisaleor-dashboard
which is the amdin area for the appsaleor-storefront
which is the user facing part of the ecommerce platform
Usually, we as developers use the first 2 components as provided by the saleor team and build a custom storefront on top of it
The problem
The saleor-dashboard
is a react app that is build as a static site in a docker container but to do that we have to provide the API_URI at the build time
so for example if you have 4 environment development
, stagging
, test
and production
then you will need to build 4 different versions of the dashboard
i looked a round to see if someone else asked the same question and i found this issue #1592
My solution
The only answer on the above mentioned issue suggested that modifying the config.ts
and index.html
file would do the trick, so i will explain how you can do it manually, then feel free to automate the process
Get the dashboard code
clone the repo and checkout the version you need to build
git clone --depth 1 --branch <ref> https://github.com/saleor/saleor.git
Config file
we will create a bash script env.sh
that read the $API_URI
env variable and generate a config javascript file, this script will run every time before the docker container started
notice that the docker container will serve the dashboard from a folder called dashboard
that is why the script will generate the env file in the same folder
#!/bin/bash
target_file=./dashboard/env-config.js
touch $target_file
rm -rf $target_file
echo "window._env_ = {" >> $target_file
echo " API_URI: \"$API_URI\"," >> $target_file
echo "}" >> $target_file
The generated file should look like this
window._env_ = {
API_URI: "<api-url-from-env>",
};
Modify src/index.html
Edit the main html file of the dashboard and add this script tag on the head
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no"
/>
<meta name="robots" content="noindex" />
<title>Saleor e-commerce</title>
<script src="/dashboard/env-config.js"></script>
<!-- add this line-->
</head>
<body>
<div id="dashboard-app"></div>
</body>
</html>
Modify src/config.ts
now we will read the API_URI
from the window
object at the runtime instead of reading it from environment at build time
import packageInfo from "../package.json";
import { SearchVariables } from "./hooks/makeSearch";
import { ListSettings, ListViews, Pagination } from "./types";
export const APP_MOUNT_URI = process.env.APP_MOUNT_URI || "/";
export const APP_DEFAULT_URI = "/";
// remove this line
export const API_URI = process.env.API_URI;
// add these 2 lines, typescript build would fail without the @ts-ignore
// @ts-ignore
export const API_URI = window._env_.API_URI;
....
....
Modify Dockerfile
for the docker file we need to do 2 things
-
copy the
env.sh
script into the docker image root -
change the command to run the
env.sh
before starting the container
FROM node:14 as builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
ARG APP_MOUNT_URI
ARG API_URI
ARG STATIC_URL
ENV API_URI ${API_URI:-http://localhost:8000/graphql/}
ENV APP_MOUNT_URI ${APP_MOUNT_URI:-/dashboard/}
ENV STATIC_URL ${STATIC_URL:-/dashboard/}
RUN STATIC_URL=${STATIC_URL} API_URI=${API_URI} APP_MOUNT_URI=${APP_MOUNT_URI} npm run build
FROM nginx:stable
WORKDIR /app
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/build/ /app/
# Add the following lines
COPY ./env.sh .
RUN chmod +x env.sh
CMD ["/bin/bash", "-c", "/app/env.sh && nginx -g \"daemon off;\""]
No you can build saleor-dashboard
image that take the API_URI
from your deployment environment
Note
For me to not repeat the above steps with every new version of the dashboard, i created a gitlab CI/CD pipeline to do this automatically for whatever version/tag/ref i specify but unfortunately this is something i can't share